// 字库芯片GT23L16U2W
// superzlc
// 20180414112525
#ifndef __GT23L16U2W_H_
#define __GT23L16U2W_H_ 1

#include <avr/io.h>
#include <util/delay.h>

#include "GT23L16U2W_ADDR.h"

//
#define FONT_DDR DDRE
#define FONT_PIN PINE
#define FONT_PORT PORTE

#define FONT_CLK_PORT_N 2
#define FONT_CS_PORT_N 3
#define FONT_SI_PORT_N 4
#define FONT_SO_PORT_N 5

//
#define FONT_CLK_1 FONT_PORT |= _BV(FONT_CLK_PORT_N)
#define FONT_CLK_0 FONT_PORT &= ~_BV(FONT_CLK_PORT_N)
#define FONT_CS_1 FONT_PORT |= _BV(FONT_CS_PORT_N)
#define FONT_CS_0 FONT_PORT &= ~_BV(FONT_CS_PORT_N)
#define FONT_SI_1 FONT_PORT |= _BV(FONT_SI_PORT_N)
#define FONT_SI_0 FONT_PORT &= ~_BV(FONT_SI_PORT_N)
#define FONT_SO_IN FONT_PIN & _BV(FONT_SO_PORT_N)
//
void font_port_init(void)
{
	FONT_DDR = FONT_DDR
		| _BV(FONT_CLK_PORT_N)
		| _BV(FONT_CS_PORT_N)
		| _BV(FONT_SI_PORT_N);
	FONT_DDR = FONT_DDR
		& ~_BV(FONT_SO_PORT_N);
}
void font_init(void)
{
	font_port_init();
	FONT_CS_1;
	FONT_CLK_0;
	FONT_SI_0;
}

uint8_t font_wr_byte(uint8_t w, uint8_t readAtFirst)
{
	uint8_t r = 0;
	uint8_t i = 0;
	for (i = 0; i < 8; i++)
	{
		if (readAtFirst)
		{
			// 时钟下降沿器件输出信号，单片机取值
			asm("nop");asm("nop");asm("nop");asm("nop"); //_delay_us(1);
			r <<= 1;
			if (FONT_SO_IN)
				r += 1;
		}
		
		// 移位输出信号
		if (w & 0b10000000)
			FONT_SI_1;
		else
			FONT_SI_0;
		w = w << 1;
		
		// 时钟上升沿
		FONT_CLK_1;
		
		// 器件锁存信号时间
		asm("nop");asm("nop");asm("nop");asm("nop"); //_delay_us(1);
		
		// 时钟下降沿
		FONT_CLK_0;
		
		if (!readAtFirst)
		{
			// 时钟下降沿器件输出信号，单片机取值
			asm("nop");asm("nop");asm("nop");asm("nop"); //_delay_us(1);
			r <<= 1;
			if (FONT_SO_IN)
				r += 1;
		}
	}
	return r;
}
void font_write_addr(uint32_t addr)
{
	font_wr_byte(0b00000011, 1);
	font_wr_byte((addr >> 16) & 0xff, 1);
	font_wr_byte((addr >> 8) & 0xff, 1);
	font_wr_byte((addr) & 0xff, 1);
}
void font_write_addr_fast(uint32_t addr)
{
	font_wr_byte(0b00001011, 1);
	font_wr_byte((addr >> 16) & 0xff, 1);
	font_wr_byte((addr >> 8) & 0xff, 1);
	font_wr_byte((addr) & 0xff, 1);
	font_wr_byte(0b11111111, 1);
}
void font_read_dots(uint8_t buff[], uint8_t size)
{
	for (uint8_t i = 0; i < size; i++)
	{
		buff[i] = font_wr_byte(0x00, 1);
	}
}
void font_read_dots_by_addr(uint32_t addr, uint8_t buff[], uint8_t size)
{
	FONT_CS_0;
	font_write_addr(addr);
	font_read_dots(buff, size);
	FONT_CS_1;
}


#endif // __GT23L16U2W_H_